/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium.util;

import fr.x9c.cadmium.kernel.Fail;
import fr.x9c.cadmium.kernel.Fatal;
import fr.x9c.cadmium.kernel.Value;

/**
 * This interface defines a Cadmium stack, that is a stack of <tt>Value</tt>
 * instances. <br/>
 * Type of stack elements is not abstracted in order to allow value-specific
 * or more generally Cadmium-specific optimizations. <br/>
 * More, a <i>classical</i> stack may disallow peeking / assignation. <br/>
 * One may also notice that althought "slice" methods use arrays, it is
 * impossible to create <tt>T</tt> arrays where <tt>T</tt> is a type parameter.
 * <br/> <br/>
 * A stack implementation should provide a way (<i>e.g.</i> by constructor
 * parameter) to specify its maximum size in order to detect stack overflows
 * in interpreted programs without the JVM running out of memory. Such a
 * problem causes a {@link fr.x9c.cadmium.kernel.Fail.Exception} to be thrown.
 * Other stack errors (such as attempt to access to an element that does not
 * exist) cause a {@link fr.x9c.cadmium.kernel.Fatal.Exception} to be thrown.
 *
 * @see fr.x9c.cadmium.kernel.Value
 * @see fr.x9c.cadmium.kernel.Fail.Exception
 * @see fr.x9c.cadmium.kernel.Fatal.Exception
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.0
 * @since 1.0
 */
public interface Stack {

    /**
     * Tests whether the stack is empty.
     * @return <tt>true</tt> if the stack is empty, <tt>false</tt> otherwise
     */
    boolean isEmpty();

    /**
     * Tests whether the stack is full (size being equal to maximum size).
     * @return <tt>true</tt> if the stack is full, <tt>false</tt> otherwise
     */
    boolean isFull();

    /**
     * Returns the size of the stack.
     * @return the size of the stack
     */
    int size();

    /**
     * Returns the maximum size of the stack. <br/>
     * Size of Cadmium stacks are bounded to diagnose stack overflows.
     * @return the maximum size of the stack
     */
    int maxSize();

    /**
     * Pushes a value onto the stack.
     * @param v value to push onto the stack - should not be <tt>null</tt>
     * @throws Fail.Exception if this operation causes a stack overflow
     *                        (that is, if the stack is full)
     */
    void push(Value v) throws Fail.Exception;

    /**
     * Pops the top value from the stack.
     * @return the top value from the stack
     * @throws Fatal.Exception if stack is empty
     */
    Value pop() throws Fatal.Exception;

    /**
     * Pops some values from the stack.
     * @param n number of values to pop - should be >= 0
     * @throws Fatal.Exception if an attempt is made to pop more values
     *                         from the stack than it contains
     */
    void pop(int n) throws Fatal.Exception;

    /**
     * Peeks a value from the stack.
     * @param idx index of value to peek (0 representing the top-most element,
     *            growing toward stack bottom) - should be >= 0
     * @return the value of the stack at index <tt>idx</tt>
     * @throws Fatal.Exception if <tt>idx</tt> refers to an element of the
     *                         stack that does not exist
     */
    Value peek(int idx) throws Fatal.Exception;

    /**
     * Assigns a value into the stack (<i>opposite</i> of peek). <br/>
     * That is, modifies an element of the stack.
     * @param idx index of value to assign
     *            (0 representing the top-most element) - should be >= 0
     * @param v value to assign into the stack - should not be <tt>null</tt>
     * @throws Fatal.Exception if <tt>idx</tt> refers to an element of the
     *                         stack that does not exist
     */
    void assign(int idx, Value v) throws Fatal.Exception;


    /**
     * Pops some values from the stack into an array. <br/>
     * Opposite of {@link #pushSlice(Value[])}.
     * @param n number of values to pop - should be >= 0
     * @return an array of size <tt>n</tt> containing the popped values <br/>
     *         top element of the stack is returned in at index <tt>n - 1</tt>
     * @throws Fatal.Exception if an attempt is made to pop more values
     *                         from the stack than it contains
     * @see #pushSlice(Value[])
     */
    Value[] popSlice(int n) throws Fatal.Exception;

    /**
     * Pushes some values onto the stack. <br/>
     * Opposite of {@link #popSlice(int)}.
     * @param s values to push onto the stack - should not be <tt>null</tt><br/>
     *          - should also not contain any null value <br/>
     *          top element of the stack is <tt>s[s.length - 1]</tt>
     * @throws Fail.Exception if this operation causes a stack overflow
     *                        (that is, if the stack is full)
     * @see #popSlice(int)
     */
    void pushSlice(Value[] s) throws Fail.Exception;

} // end interface 'Stack'
